package com.sumer.psychology.space.infrastructure.persistence.mongo.friend;

import com.google.gson.Gson;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
import com.sumer.psychology.common.domain.model.User;
import com.sumer.psychology.common.domain.model.UserService;
import com.sumer.psychology.space.domain.FriendMessageType;
import com.sumer.psychology.space.domain.MessageType;
import com.sumer.psychology.space.infrastructure.persistence.mongo.MongoMessageRepository;
import com.sumer.psychology.space.infrastructure.persistence.mongo.SpaceDomainRegistry;

import javax.inject.Inject;

/**
 * 朋友关系message
 * <p/>
 * User: zhenguang.zhu
 * Date: 2014/11/24
 * Time: 9:07
 */
public abstract class MongoFriendMessageRepository extends MongoMessageRepository {
    private static Gson gson = new Gson();

    public static MongoFriendMessageRepository create(FriendMessageType friendMessageType) {
        switch (friendMessageType) {
            case REQUEST:
                return SpaceDomainRegistry.friendRequestMessageRepository();
            case REJECT:
                return SpaceDomainRegistry.friendRejectMessageRepository();
            case ADD:
                return SpaceDomainRegistry.friendAddMessageRepository();
            case DELETE:
                return SpaceDomainRegistry.friendDeleteMessageRepository();
            default:
                return SpaceDomainRegistry.friendRequestMessageRepository();
        }
    }

    private UserService userService;

    /**
     * 创建message
     *
     * @param requester    requester
     * @param acceptor     acceptor
     * @param friend       friend
     * @param messageWords message words
     * @return db object
     */
    protected DBObject message(
            User requester,
            User acceptor, DBObject friend, String messageWords) {
        Object ownerId = friend.get("_id");
        Object words = messageWords == null ? null : friend.get(messageWords);

        DBObject requestDB = (DBObject) JSON.parse(gson.toJson(requester));
        DBObject acceptDB = (DBObject) JSON.parse(gson.toJson(acceptor));

        requestDB.removeField("profile");
        acceptDB.removeField("profile");
        BasicDBObject result = new BasicDBObject()
                .append("requester", requestDB)
                .append("acceptor", acceptDB)
                .append("friendMessageType", friendMessageType().toString())
                .append("ownerIsAcceptor", acceptDB.get("identity").equals(ownerId));
        if (words != null) {
            result.append(messageWords, words);
        }

        if (friend.get("messageId") != null) {
            result.append("messageId", friend.get("messageId"));
        }

        result.append("messageType", MessageType.FRIEND.toString());
        return result;
    }

    /**
     * 获得User
     *
     * @param requesterId request id
     * @return user
     */
    protected User user(String requesterId) {
        return userService.userFrom(requesterId);
    }

    protected abstract FriendMessageType friendMessageType();

    /**
     * 保存消息
     *
     * @param data        data
     * @param from        from key
     * @param to          to key
     * @param removeField removed fields
     */
    protected void add(String data, String from, String to, String removeField) {
        DBObject friendEvent = initializeData(data, from + ".identity");
        String requesterId = (String) friendEvent.get("_id");
        String acceptorId = nestedValue(friendEvent, to + ".identity");
        friendEvent.removeField(to);

        User requester = user(requesterId);
        User acceptor = user(acceptorId);

        friendEvent.put("owner_name", requester.name());
        DBObject requesterMessage = message(requester, acceptor, friendEvent, removeField);

        if (removeField != null) {
            friendEvent.removeField(removeField);
        }
        friendEvent.removeField("messageId");

        // 保存发送者
        update(friendEvent, requesterMessage);

        // 保存接收者
        if (!acceptorId.equals(requesterId)) {
            friendEvent.put("_id", acceptorId);
            friendEvent.put("owner_name", acceptor.name());
            requesterMessage.put("ownerIsAcceptor", true);
            update(friendEvent, requesterMessage);
        }
    }

    @Override
    public void add(String data) {
        add(data, "requesterId", "acceptorId", null);
    }

    /**
     * 给朋友消息设置状态
     *
     * @param id        id
     * @param messageId message id
     */
    public void setStatusToRequestMessage(String id, String messageId) {
        db().getCollection(dbName()).update(
                new BasicDBObject("_id", id)
                        .append("messages.message_id", messageId)
                        .append("messages.friendMessageType", FriendMessageType.REJECT.toString()),
                new BasicDBObject("$set", new BasicDBObject("messages.$.status", "complete")));
    }

    @Inject
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}